<template>
	<div v-if="isPureText" class="center" :style="[buttonStyle]" @click="$emit('click')">
		<slot><CaLabel :text="title" button/></slot>
	</div>
	<button v-else :size="size" :type="type" :plain="plain" :disabled="disabled" :loading="loading" :form-type="formType" :open-type="openType"
		:hover-class="hoverClass" :hover-start-time="hoverStartTime" :hover-stay-time="hoverStayTime" :app-parameter="appParameter"
		:hover-stop-propagation="hoverStopPropagation" :lang="wxlang" :session-from="sessionFrom" :send-message-title="sendMessageTitle" :send-message-path="sendMessagePath" :send-message-img="sendMessageImg" :show-message-card="showMessageCard"
		:group-id="groupId" :guild-id="guildId" :public-id="publicId" 
		:data-im-id="dataImId" :data-im-type="dataImType" :data-goods-id="dataGoodsId" :data-order-id="dataOrderId" :data-biz-id="dataBizId"
		@getphonenumber="onEvent('getphonenumber', $event)" @getuserinfo="onEvent('getuserinfo', $event)" @error="onEvent('error', $event)" @opensetting="onEvent('opensetting', $event)"  @launchapp="onEvent('launchapp', $event)" @contact="onEvent('contact', $event)"
		@chooseavatar="onEvent('chooseavatar', $event)" @agreeprivacyauthorization="onEvent('agreeprivacyauthorization', $event)" @addgroupapp="onEvent('addgroupapp', $event)" @chooseaddress="onEvent('chooseaddress', $event)" @chooseinvoicetitle="onEvent('chooseinvoicetitle', $event)"
		@subscribe="onEvent('subscribe', $event)" @login="onEvent('login', $event)" @im="onEvent('im', $event)"
		@click="onClick('click', $event)" @scroll="onClick('scroll', $event)" @longpress="onClick('longpress', $event)"
		@dblclick="onClick('dblclick', $event)" @wheel="onMouse('wheel', $event)" @mouseenter="onMouse('mouseenter', $event)" @mousedown="onMouse('mousedown', $event)" @mouseleave="onMouse('mouseleave', $event)" @mousemove="onMouse('mousemove', $event)" @mouseout="onMouse('mouseout', $event)" @mouseover="onMouse('mouseover', $event)" @mouseup="onMouse('mouseup', $event)"
		:onClick="`event.cancelBubble = ${cancelBubble}`" :style="[buttonStyle]" class="center"
	>
		{{title}}
		<slot v-if="!title"></slot>
	</button>
</template>

<script>
	
	import base from '@/components/index.vue'
	
	export default {
		extends: base,
		emits: [
			'click', // 点击事件，或者鼠标单机
			'longpress', // 长按事件
			'dblclick', // 鼠标双击
			'scroll', // 页面滚动时触发的事件。针对的是窗口滚动
			'wheel', // 使用鼠标滚轮时触发的事件。针对的是鼠标滚轮
			'mouseenter', // 鼠标指针进入被选元素时,会发生mousedown事件
			'mousedown', // 鼠标指针移动到元素上方时,并按下鼠标左键,发生mousedown事件。
			'mouseleave', // 是指鼠标离开被选元素时，发生mouseleave事件。
			'mousemove', // 鼠标指针在指定的元素中移动时，发生 mousemove 事件。
			'mouseout', // 在鼠标指针离开被选元素或任意子元素时，都会被触发。
			'mouseover', // 鼠标指针位于元素上方时， 会发生 mouseover 事件。
			'mouseup', // 鼠标指针移动到元素上方， 并松开鼠标左键时， 会发生 mouseup 事件。
			
			'getphonenumber', // 获取用户手机号的回调。open-type="getPhoneNumber"。微信、支付宝、百度、抖音、快手、京东小程序
			'getuserinfo', // 用户点击该按钮时，会返回获取到的用户信息，从返回参数的detail中获取到的值同uni.getUserInfo。open-type="getUserInfo"。微信、QQ、百度、快手、京东小程序
			'error', // 当使用开放能力时，发生错误的回调。open-type="launchApp"。微信、QQ、快手、京东小程序
			'opensetting', // 在打开授权设置页并关闭后回调。open-type="openSetting"。微信、QQ、百度、快手、京东小程序
			'launchapp', // 从小程序打开 App 成功的回调。open-type="launchApp"。微信、QQ、快手、京东小程序
			'contact', // 客服消息回调。open-type="contact"。微信、QQ、百度、快手小程序
			'chooseavatar', // 获取用户头像回调。open-type="chooseAvatar"。微信小程序
			'agreeprivacyauthorization', // 用户同意隐私协议事件回调。open-type="agreeprivacyauthorization"。微信小程序
			'addgroupapp', // 添加群应用的回调。open-type="addGroupApp"。QQ小程序
			'chooseaddress', // 调起用户编辑并选择收货地址的回调。open-type="chooseAddress"。百度小程序
			'chooseinvoicetitle', // 用户选择发票抬头的回调。open-type="chooseInvoiceTitle"。百度小程序
			'subscribe', // 订阅消息授权回调。open-type="subscribe"。百度小程序
			'login', // 登录回调。open-type="login"。百度小程序
			'im', // 监听跳转IM的成功回调。open-type="im"。抖音小程序
		],
		props: {
			/**系统按钮属性*/
			/**
			 * 按钮大小。mini：小尺寸；default：默认尺寸
			 * style和class的优先级，高于size和type属性
			 */
			size: {
				type: String,
				default: 'default'
			},
			/**
			 * 按钮的样式类型。实际控制的是buttonType，相互影响组成自定义的buttonStyle
			 * default：白色
			 * primary：微信小程序、360小程序为绿色，App、H5、百度小程序、支付宝小程序、飞书小程序、快应用为蓝色，抖音小程序为红色，QQ小程序为浅蓝色。如想在多端统一颜色，请改用default，然后自行写样式
			 * warn：红色
			 * style和class的优先级，高于size和type属性
			 */
			type: {
				type: String,
				default: 'default'
			},
			// 按钮是否镂空，背景色透明
			plain: Boolean,
			// 是否禁用
			disabled: Boolean,
			// 名称前是否带 loading 图标
			loading: Boolean,
			/**
			 * 用于 <form> 组件，点击分别会触发 <form> 组件的 submit/reset 事件
			 */
			formType: String,
			/**
			 * 开放能力
			 *  feedback	打开“意见反馈”页面，用户可提交反馈内容并上传日志	App、微信小程序、QQ小程序。
			  		小程序中，开发者可以登录 微信小程序管理后台 、QQ小程序后台后，进入菜单“客服反馈”页面获取反馈内容。
					在 App 中，开发者登录 DCloud开发者中心 后点击应用名称，进入左侧菜单“用户反馈”页面获取反馈内容。
				share	触发用户转发	微信小程序、百度小程序、支付宝小程序、抖音小程序、飞书小程序、QQ小程序、快手小程序、京东小程序、360小程序
				getUserInfo	获取用户信息，可以从@getuserinfo回调中获取到用户信息	微信小程序、百度小程序、QQ小程序、快手小程序、京东小程序、360小程序
				contact	打开客服会话，如果用户在会话中点击消息卡片后返回应用，可以从 @contact 回调中获得具体信息	微信小程序、百度小程序、快手小程序、抖音小程序
				getPhoneNumber	获取用户手机号，可以从@getphonenumber回调中获取到用户信息	微信小程序、百度小程序、抖音小程序、支付宝小程序、快手小程序、京东小程序。App平台另见一键登陆
				launchApp	小程序中打开APP，可以通过app-parameter属性设定向APP传的参数	微信小程序、QQ小程序、快手小程序、京东小程序
				openSetting	打开授权设置页	微信小程序、QQ小程序、百度小程序、快手小程序、京东小程序、360小程序
				chooseAvatar	获取用户头像，可以从@chooseavatar回调中获取到头像信息	微信小程序2.21.2版本+
				agreePrivacyAuthorization	用户同意隐私协议按钮。用户点击一次此按钮后，所有隐私接口可以正常调用。可通过 @agreeprivacyauthorization 监听用户同意隐私协议事件。隐私合规开发指南详情可见《小程序隐私协议开发指南》	微信小程序2.33.0版本+
				uploadDouyinVideo	发布抖音视频	抖音小程序2.65.0版本+
				im	跳转到抖音IM客服	抖音小程序2.80.0版本+
				getAuthorize	支持小程序授权	支付宝小程序
				lifestyle	关注生活号	支付宝小程序
				contactShare	分享到通讯录好友	支付宝小程序基础库1.11.0版本+
				openGroupProfile	呼起QQ群资料卡页面，可以通过group-id属性设定需要打开的群资料卡的群号，同时manifest.json中必须配置groupIdList	QQ小程序基础库1.4.7版本+
				openGuildProfile	呼起频道页面，可以通过guild-id属性设定需要打开的频道ID	QQ小程序基础库1.46.8版本+
				openPublicProfile	打开公众号资料卡，可以通过public-id属性设定需要打开的公众号资料卡的号码，同时manifest.json中必须配置publicIdList	QQ小程序基础库1.12.0版本+
				shareMessageToFriend	在自定义开放数据域组件中,向指定好友发起分享据	QQ小程序基础库1.17.0版本+
				addFriend	添加好友， 对方需要通过该小程序进行授权，允许被加好友后才能调用成功用户授权	QQ小程序
				addColorSign	添加彩签，点击后添加状态有用户提示，无回调	QQ小程序基础库1.10.0版本+
				addGroupApp	添加群应用（只有管理员或群主有权操作），添加后给button绑定@addgroupapp事件接收回调数据	QQ小程序基础库1.16.0版本+
				addToFavorites	收藏当前页面，点击按钮后会触发Page.onAddToFavorites方法	QQ小程序基础库1.19.0版本+
				chooseAddress	选择用户收货地址，可以从@chooseaddress回调中获取到用户选择的地址信息	百度小程序3.160.3版本+
				chooseInvoiceTitle	选择用户发票抬头，可以从@chooseinvoicetitle回调中获取到用户选择发票抬头信息	百度小程序3.160.3版本+
				login	登录，可以从@login回调中确认是否登录成功	百度小程序3.230.1版本+
				subscribe	订阅类模板消息，需要用户授权才可发送	百度小程序
				favorite	触发用户收藏	快手小程序
				watchLater	触发用户稍后再看	快手小程序
				openProfile	触发打开用户主页	快手小程序
			 */
			openType: String,
			/**
			 * 指定按钮按下去的样式类。当 hover-class="none" 时，没有点击态效果
			 * 默认值是"button-hover"。{background-color: rgba(0, 0, 0, 0.1); opacity: 0.7;}
			 * button虽然可以内嵌text组件，但不建议通过text组件来修改button样式，因为会导致hover-class不生效。
			 * 尤其是uvue中样式不继承。建议直接在button组件的style或class属性编写样式。style和class的优先级，高于size和type属性。
			 */
			hoverClass: String,
			// 按住后多久出现点击态，单位毫秒
			hoverStartTime: {
				type: Number,
				default: 20
			},
			// 手指松开后点击态保留时间，单位毫秒
			hoverStayTime: {
				type: Number,
				default: 70
			},
			/**
			 * 打开 APP 时，向 APP 传递的参数，open-type=launchApp时有效
			 * 微信小程序、QQ小程序
			 */
			appParameter: String,
			// 指定是否阻止本节点的祖先节点出现点击态。微信小程序
			hoverStopPropagation: Boolean,
			/**
			 * 指定返回用户信息的语言，
			 * zh_CN 简体中文，
			 * zh_TW 繁体中文，
			 * en 英文。
			 * 微信小程序
			 */
			wxlang: {
				type: String,
				default: 'en'
			},
			// 会话来源，open-type="contact"时有效。微信小程序
			sessionFrom: String,
			// 会话内消息卡片标题，open-type="contact"时有效。微信小程序。默认值当前标题
			sendMessageTitle: String,
			// 会话内消息卡片点击跳转小程序路径，open-type="contact"时有效。微信小程序。默认值当前分享路径
			sendMessagePath: String,
			// 会话内消息卡片图片，open-type="contact"时有效。微信小程序。默认值截图
			sendMessageImg: String,
			// 是否显示会话内消息卡片，设置此参数为 true，用户进入客服会话会在右下角显示"可能要发送的小程序"提示，用户点击后可以快速发送小程序消息，open-type="contact"时有效。微信小程序
			showMessageCard: Boolean,
			// 打开群资料卡时，传递的群号。open-type="openGroupProfile"。QQ小程序
			groupId: String,
			// 打开频道页面时，传递的频道号。open-type="openGroupProfile"。QQ小程序
			guildId: String,
			// 打开公众号资料卡时，传递的号码。open-type="openGroupProfile"。QQ小程序
			publicId: String,
			// 客服的抖音号。open-type="im"。抖音小程序
			dataImId: String,
			// IM卡片类型。open-type="im"。抖音小程序
			dataImType: String,
			// 商品的id，仅支持泛知识课程库和生活服务商品库中的商品。open-type="im"。抖音小程序
			dataGoodsId: String,
			// 订单的id，仅支持交易2.0订单。open-type="im"。抖音小程序
			dataOrderId: String,
			// 商品类型，“1”代表生活服务，“2”代表泛知识。。open-type="im"。抖音小程序
			dataBizId: String,
			
			/**自定义属性*/
			// 按钮文字
			title: String,
			// 是否纯文字。纯文字没有背景颜色和边框
			isPureText: Boolean,
			// 标题文字的宽度
			width: [String, Number],
			// 按钮的高度
			height: [String, Number],
			// 按钮的圆角
			radius: [String, Number],
			/**
			 * 是否阻隔事件传递。该值对小程序无效。
			 * 对策：
			 * 1，外面包一层div使用click.stop=e => core.common.onStop(e)
			 * 2，event.stopPropagation()
			 * 实测2无效！
			 */
			cancelBubble: {
				type: Boolean,
				default: true
			},
			// 背景颜色
			backgroundColor: String,
			// 文字颜色
			titleColor: String, 
			// 文字大小
			fontSize: [String, Number],
			// 文字左边的图标
			fixIcon: String,
			// 文字右边的图标
			rightIcon: String,
			// 图标的大小。如果存在，将会代替默认值
			iconSize: [String, Number],
			// 图片旋转的角度
			iconTransform: [String, Number],
			// 其它的样式
			customStyle: Object,
			/**
			 * button类型
			 * submit：提交 - 需传入backgroundColor，文字始终白色
			 * normal：一般类型
			 * disabled：禁用
			 * warn：警告 - 边框红色
			 */
			buttonType: {
				type: String,
				default: 'normal'
			},
			/**
			 * 最少间隔多久可以再点击
			 * 默认1000毫秒
			 */
			least: {
				type: [String, Number],
				default: 1000
			},
		},
		data() {
			return {
				buttonStyle: {}
			}
		},
		methods: {
			// 鼠标事件
			onMouse(type, event) {
				this.$emit(type, event)
			},
			
			// 点击事件
			onClick(type, event) {
				if (this.disabled || this.buttonType === 'disabled') {
					// 禁用中
				} else {
					if (this.isloading) {
						this.core.showToast('请勿重复点击')
					} else {
						if (this.cancelBubble) {
							/**
							 * cancelBubble在小程序中不生效
							 * 须使用click.stop => onStop事件
							 * 但是click.stop会完全阻隔父组件接收事件，无法解决这个矛盾
							 */
							event.stopPropagation && event.stopPropagation() // 阻止事件冒泡
							this.handleClick(type)
						} else {
							this.handleClick(type)
						}
					}
				}
			},
			
			// 实际事件处理
			handleClick(type) {
				// 按钮恢复可点
				const resume = (loading = false) => {
					if (this.least) {
						this.core.delayAction(() => {
							this.isloading = loading
						}, this.least)
					} else {
						this.isloading = loading
					}
				}
				// 按钮变为不可点
				this.isloading = true
				/**
				 * 回调事件，同时传递按钮恢复的方法
				 * resume的参数是true：继续加载中，不可点；false：恢复为可点状态
				 */
				this.$emit(type, resume)
				// 默认也会恢复
				resume()
			},
			
			/**
			 * 开发能力的事件
			 * 如果获取不到参数e，需调整接收的方式
			 * @param {Object} type
			 * @param {Object} event
			 */
			onEvent(type, event) {
				this.$emit(type, event)
			}
		}
	}
</script>

<style>
</style>